package com.wl.api.service.system.impl;

import static com.wl.api.common.utils.PageInfo.transformPage;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.wl.api.common.utils.BeanUtils;
import com.wl.api.common.utils.CollectionUtil;
import com.wl.api.common.utils.ObjectUtil;
import com.wl.api.common.utils.PageInfo;
import com.wl.api.common.utils.StringUtil;
import com.wl.api.dto.system.SecurityModuleDTO;
import com.wl.api.dto.system.SecurityRoleDTO;
import com.wl.api.mapper.system.SecurityRoleMapper;
import com.wl.api.model.system.SecurityModule;
import com.wl.api.model.system.SecurityRole;
import com.wl.api.model.system.SecurityRolePermission;
import com.wl.api.service.system.ISecurityModuleService;
import com.wl.api.service.system.ISecurityRolePermissionService;
import com.wl.api.service.system.ISecurityRoleService;

/**
 *
 * SecurityRole 表数据服务层接口实现类
 *
 */
@Service
public class SecurityRoleServiceImpl extends ServiceImpl<SecurityRoleMapper, SecurityRole> implements ISecurityRoleService {
    @Autowired
    ISecurityRolePermissionService rolePermissionService;
    
    @Autowired
    ISecurityModuleService moduleService;
    
    @Autowired
    SecurityRoleMapper roleMapper;
    
    public String getRoleNameByUserID(Long userID) {
    	return roleMapper.getRoleNameByUserID(userID);
    }
    
	@Transactional
	public int createRoleAndPermission(SecurityRoleDTO role) {
		SecurityRole entity = SecurityRole.builder().name(role.getName()).build();
		insert(entity);
		rolePermissionService.insertBatch(role.getModuleList().parallelStream()
				.map(s -> SecurityRolePermission.builder().permission(s).updateId(role.getUpdateId()).updateUser(role.getUpdateUser()).roleId(entity.getId()).build()).collect(Collectors.toList()));
		return entity.getId().intValue();
	}
	
	@Transactional
	public int updateRoleAndPermission(SecurityRoleDTO role) throws Exception {
		if (role.isDeleted()) {
			delRole(role.getId());
			return 0;
		}
		Assert.isTrue(role != null && role.getId() != null &&  !CollectionUtil.isEmpty(role.getModuleList()));;
		updateAllRole(role);	
		return role.getId().intValue();
		
	}
	@Transactional
	public boolean delRole(long roleId) {
		//角色权限被使用,不能直接删除角色
		if (rolePermissionService.selectCount(new EntityWrapper<SecurityRolePermission>().where("role_id={0}", roleId).and(" is_deleted=0")) > 0) {
			return false;
		}
		rolePermissionService.deleteById(roleId);
		deleteById(roleId);
		return true;
	}
	
	public PageInfo<SecurityRoleDTO> getRoleListPage(SecurityRoleDTO param) {
		Page<SecurityRole> page = selectPage(new Page<>(param.getPage(), param.getPageSize()), new Wrapper<SecurityRole>() {

			@Override
			public String getSqlSegment() {
				StringBuilder sb = new StringBuilder();
				sb.append(" where 1=1 ");
				if (param.getId() != null) {
					sb.append(" and id = ");
					sb.append(param.getId());
				}
				if (!StringUtil.isEmpty(param.getName())) {
					sb.append(" and name  like '");
					sb.append(param.getName());
					sb.append("'");
				}
				return sb.toString();
			}
		});
		return transformPage(SecurityRoleDTO.class, page);
	}
	/**
	 * 获取角色权限详情(所有模块,选中该角色分配的权限)
	 * @return
	 */
	public SecurityRoleDTO getRolePermissionDetail(long roleId) {
		List<SecurityModule> modules = moduleService.selectList(new EntityWrapper<SecurityModule>());
		SecurityRoleDTO role = BeanUtils.copyProperties(selectById(roleId), SecurityRoleDTO.class);
		if (CollectionUtil.isEmpty(modules)) {
			return role;
		}
		List<SecurityModuleDTO> list = modules.parallelStream().map(s -> SecurityModuleDTO.builder().id(s.getId()).name(s.getName()).parentId(s.getParentId()).sn(s.getSn()).build()).collect(Collectors.toList());
		List<SecurityRolePermission> rolePermissions = rolePermissionService.selectList(new EntityWrapper<SecurityRolePermission>().where("role_id={0}", roleId).and(" is_deleted = 0 "));
		
		return role.buildAllModuleList(makeTree(list, CollectionUtil.isEmpty(rolePermissions) ? new ArrayList<String>():
							rolePermissions.parallelStream().map(s -> s.getPermission()).distinct().collect(Collectors.toList())));
	}
	
	private List<SecurityModuleDTO> makeTree(List<SecurityModuleDTO> list, List<String> snList) {
		List<SecurityModuleDTO> parent =  list.parallelStream().filter(s -> !ObjectUtil.isEmpty(s.getParentId()) && Objects.equals(s.getParentId(), 0)).collect(Collectors.toList());
		for (SecurityModuleDTO m : parent) {
			m.setChildren(makeChildren(m, list, snList));
		}
		return parent;
	}
	
	private List<SecurityModuleDTO> makeChildren(SecurityModuleDTO parent, List<SecurityModuleDTO> children, List<String> snList) {
		if (children.isEmpty()) {
			return null;
		}
		
		List<SecurityModuleDTO> tmp = new ArrayList<SecurityModuleDTO>();
		for (SecurityModuleDTO source : children) {
			if (Objects.equals(parent.getId(), source.getParentId())) {
				tmp.add(SecurityModuleDTO.builder().id(source.getId()).permissionStatus(snList.contains(source.getSn())? 1: 0).name(source.getName()).children(makeChildren(source, children, snList)).build());
			}
		}
		
		children.removeAll(tmp);
		return tmp;
	}
	
	/** 
	 * @param role
	 */
	
	private void updateAllRole(SecurityRoleDTO role){
		updateById(SecurityRole.builder().name(role.getName()).id(role.getId()).build());
		List<SecurityRolePermission> list = rolePermissionService.selectList(new Wrapper<SecurityRolePermission>() {

			@Override
			public String getSqlSegment() {
				return  " where role_id = " + role.getId() +" and is_deleted = 0 ";
			}
		});
		
		if (CollectionUtil.isEmpty(list)) {
			rolePermissionService.insertBatch(role.getModuleList().parallelStream()
					.map(s -> SecurityRolePermission.builder().permission(s).updateId(role.getUpdateId()).updateUser(role.getUpdateUser()).roleId(role.getId()).build()).collect(Collectors.toList()));
			return ;
		}
		Set<String> newPermission = new HashSet<>(role.getModuleList());
		List<String> delPermission = new ArrayList<>();
		for(SecurityRolePermission permi: list) {
			if (!newPermission.contains(permi.getPermission())) {
				delPermission.add(permi.getPermission());
				newPermission.remove(permi.getPermission());
			}
		}
		if (newPermission.size() == list.size()) {
			return;
		}
		if (!CollectionUtil.isEmpty(newPermission)) {
			rolePermissionService.insertBatch(role.getModuleList().parallelStream()
					.map(s -> SecurityRolePermission.builder().permission(s).updateId(role.getUpdateId()).updateUser(role.getUpdateUser()).roleId(role.getId()).build()).collect(Collectors.toList()));
		}
		if (!CollectionUtil.isEmpty(delPermission)) {
			for(String permiss : delPermission) {
				rolePermissionService.update(SecurityRolePermission.builder().isDeleted(1).build(), new Wrapper<SecurityRolePermission>() {
	
					@Override
					public String getSqlSegment() {
						return " where role_id = "+ role.getId() +" and permission = '"+ permiss +"'";
					}
				});
			}
		}
		
	}
	
	

}